package com.pzh.assignment.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pzh.assignment.common.bean.Result;
import com.pzh.assignment.common.bean.vo.TaskFinalVO;
import com.pzh.assignment.common.bean.vo.TaskFinalWorkloadVO;
import com.pzh.assignment.common.bean.vo.TaskVO;
import com.pzh.assignment.common.bean.vo.TaskWorkloadVO;
import com.pzh.assignment.common.shiro.ShiroUtils;
import com.pzh.assignment.entity.Course;
import com.pzh.assignment.entity.CourseType;
import com.pzh.assignment.entity.Grade;
import com.pzh.assignment.entity.Groups;
import com.pzh.assignment.entity.Major;
import com.pzh.assignment.entity.Plan;
import com.pzh.assignment.entity.Program;
import com.pzh.assignment.entity.Role;
import com.pzh.assignment.entity.Semester;
import com.pzh.assignment.entity.Task;
import com.pzh.assignment.entity.TaskFinal;
import com.pzh.assignment.entity.User;
import com.pzh.assignment.service.ICourseService;
import com.pzh.assignment.service.ICourseTypeService;
import com.pzh.assignment.service.IGradeService;
import com.pzh.assignment.service.IGroupsService;
import com.pzh.assignment.service.IMajorService;
import com.pzh.assignment.service.IPlanService;
import com.pzh.assignment.service.IProgramService;
import com.pzh.assignment.service.ISemesterService;
import com.pzh.assignment.service.ITaskFinalService;
import com.pzh.assignment.service.ITaskService;
import com.pzh.assignment.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author pengzhihao
 * @since 2022-04-16
 */
@RestController
@RequestMapping("/task-final")
public class TaskFinalController {

    @Autowired
    ITaskFinalService taskFinalService;
    @Autowired
    ITaskService taskService;
    @Autowired
    IPlanService planService;
    @Autowired
    IProgramService programService;
    @Autowired
    ISemesterService semesterService;
    @Autowired
    IUserService userService;
    @Autowired
    IMajorService majorService;
    @Autowired
    ICourseService courseService;
    @Autowired
    ICourseTypeService courseTypeService;
    @Autowired
    IGradeService gradeService;
    @Autowired
    IGroupsService groupsService;


    @PostMapping
    public Result save(){
        TaskFinal taskFinal = null;
        List<Task> taskList = taskService.list();
        for (Task task : taskList) {
            User teacher = userService.getById(task.getTeacherId());
            Plan plan = planService.getById(task.getPlanId());
            Program program = programService.getById(plan.getProgramId());
            Semester semester = semesterService.getById(plan.getSemesterId());
            Major major = majorService.getById(program.getMajorId());
            Grade grade = gradeService.getById(program.getGradeId());
            Course course = courseService.getById(program.getCourseId());
            CourseType courseType = courseTypeService.getById(course.getTypeId());
            taskFinal = new TaskFinal();
            taskFinal.setExperimental(program.getExperimental());
            taskFinal.setTheoretical(program.getTheoretical());
            taskFinal.setCredit(program.getCredit());
            taskFinal.setTeacher(teacher.getUsername());
            taskFinal.setMerge(task.getMerge());
            taskFinal.setActualNum(task.getActualNum());
            taskFinal.setMaxNum(task.getMaxNum());
            taskFinal.setCommonNum(task.getCommonNum());
            taskFinal.setMajor(major.getName());
            taskFinal.setCourseName(course.getName());
            taskFinal.setCourseType(courseType.getName());
            taskFinal.setGrade(grade.getGrade());
            Integer next = semester.getYear() + 1;
            String seme = semester.getYear() + "-" + next + "-" + semester.getNumber();
            taskFinal.setSemester(seme);
            taskFinalService.save(taskFinal);
            taskService.removeById(task.getId());
        }
        planService.remove(new QueryWrapper<Plan>().eq("remain_num", 0));
        return Result.success(null);
    }

    @GetMapping("/page")
    public Result pageTaskFinalWorkloadVO(@RequestParam(defaultValue = "1") Integer currentPage,
                                          @RequestParam(defaultValue = "5") Integer size) {
        Page<TaskFinal> page = new Page<>(currentPage, size);
        ArrayList<String> columns = new ArrayList<>();
        columns.add("teacher");
        columns.add("semester");
        QueryWrapper<TaskFinal> taskFinalQueryWrapper = initTaskFinalWrapper(columns);
        IPage pageData = taskFinalService.page(page, taskFinalQueryWrapper);
        List<TaskFinalWorkloadVO> voList = ((IPage<TaskFinal>) pageData).getRecords().stream().map(TaskFinalWorkloadVO::valueOf).collect(Collectors.toList());
        calculate(voList);
        pageData.setRecords(voList);
        return Result.success(pageData);
    }

    @GetMapping("/total")
    public Result totalTaskFinalWorkloadVO() {
        ArrayList<String> columns = new ArrayList<>();
        columns.add("teacher");
        QueryWrapper<TaskFinal> taskFinalQueryWrapper = initTaskFinalWrapper(columns);
        List<TaskFinal> taskFinals = taskFinalService.list(taskFinalQueryWrapper);
        List<TaskFinalWorkloadVO> vos = taskFinals.stream().map(TaskFinalWorkloadVO::valueOf).collect(Collectors.toList());
        calculate(vos);
        return Result.success(vos);
    }


    @GetMapping
    public Result listTaskFinalVOByTeacher(@RequestParam String name,
                                           @RequestParam String semester) {
        HashMap<String, String> queryMap = new HashMap<>();
        queryMap.put("teacher", name);
        queryMap.put("semester", semester);
        List<TaskFinal> taskFinals = taskFinalService.list(new QueryWrapper<TaskFinal>().allEq(queryMap));
        List<TaskFinalVO> taskFinalVOS = taskFinals.stream().map(TaskFinalVO::valueOf).collect(Collectors.toList());
        return Result.success(taskFinalVOS);
    }

    @GetMapping("/proposal")
    public Result proposalTeacher(@RequestParam String courseName) {
        List<TaskFinal> finalList = taskFinalService.list(new QueryWrapper<TaskFinal>().eq("course_name", courseName));
        List<String> totalList = finalList.stream().map(taskFinal -> taskFinal.getTeacher()).collect(Collectors.toList());
        List<String> teacherList = totalList.stream().distinct().collect(Collectors.toList());
        Map<String, Integer> teacherMap = teacherList.stream().collect(Collectors.toMap(teacher -> teacher, teacher -> 0));
        //统计教师出现的次数
        for (String teacher : totalList) {
            Integer count = teacherMap.get(teacher);
            teacherMap.put(teacher, count + 1);
        }
        List<String> proposalTeacher = findProposalTeacher(teacherMap, 3);
        return Result.success(proposalTeacher);
    }

    private void calculate(List<TaskFinalWorkloadVO> voList) {
        DecimalFormat df = new DecimalFormat("#.##");
        for (TaskFinalWorkloadVO taskFinalWorkloadVO : voList) {
            HashMap<String, String> queryMap = new HashMap<>();
            queryMap.put("teacher", taskFinalWorkloadVO.getTeacher());
            queryMap.put("semester", taskFinalWorkloadVO.getSemester());
            List<TaskFinal> taskFinals = taskFinalService.list(new QueryWrapper<TaskFinal>().allEq(queryMap));
            float workload = 0;
            for (TaskFinal taskFinal : taskFinals) {
                Integer teacheNum = taskFinal.getActualNum();//获取教学班实际人数
                Integer mostNum = taskFinal.getMaxNum();//获取教学班上限人数
                Integer commonNum = taskFinal.getCommonNum();//获取标准班人数
                float credit = taskFinal.getCredit();//获取学分
                float workNumber = (float) Math.max(Math.min( teacheNum, mostNum), commonNum)/(float) commonNum * credit;
                workload += workNumber;
            }
            taskFinalWorkloadVO.setWorkload(Float.parseFloat(df.format(workload)));
        }
    }

    /**
     * @description:  找到teacherMap中位于出现次数排行前index个的教师姓名
     * @param: teacherMap
     * @param: index
     * @return: java.util.List<java.lang.String>
     * @author pengzhihao
     * @date: 2022/5/16
     */
    private List<String> findProposalTeacher(Map<String, Integer> teacherMap, Integer index) {
        ArrayList<String> teachers = new ArrayList<>();
        List<Integer> values = teacherMap.values().stream().collect(Collectors.toList());
        if (values.size() < index) {
            //教师人数不够时直接返回
            return teacherMap.keySet().stream().collect(Collectors.toList());
        }
        //todo 排序优化
        Collections.sort(values);
        Integer flag = values.get(values.size() - index);
        Set<String> keySet = teacherMap.keySet();
        for (String key : keySet) {
            if (teacherMap.get(key) >= flag) {
                teachers.add(key);
            }
        }
        return teachers;
    }

    private QueryWrapper<TaskFinal> initTaskFinalWrapper(List<String> columns){
        Role role = ShiroUtils.getProfile().getRole();
        Integer groupId = ShiroUtils.getProfile().getGroupId();
        QueryWrapper<TaskFinal> wrapper = new QueryWrapper<>();
        switch (role.getName()) {
            case Role.SYSTEM_ADMIN:{
                wrapper.groupBy(columns);
                break;
            }
            case Role.ORG_ADMIN:{
                Groups group = groupsService.getById(groupId);
                List<Groups> groupsList = groupsService.list(new QueryWrapper<Groups>().eq("college_id", group.getCollegeId()));
                List<Integer> groupIds = groupsList.stream().map(groups -> groups.getId()).collect(Collectors.toList());
                List<User> userList = userService.list(new QueryWrapper<User>().in("group_id", groupIds));
                List<String> teacherNames = userList.stream().map(user -> user.getUsername()).collect(Collectors.toList());
                wrapper.in("teacher", teacherNames).groupBy(columns);
                break;
            }
            case Role.ADMIN:{
                List<User> userList = userService.list(new QueryWrapper<User>().eq("group_id", groupId));
                List<String> teacherNames = userList.stream().map(user -> user.getUsername()).collect(Collectors.toList());
                wrapper.in("teacher", teacherNames).groupBy(columns);
                break;
            }
            case Role.TEACHER:{
                Integer teacherId = ShiroUtils.getProfile().getId();
                User teacher = userService.getById(teacherId);
                wrapper.eq("teacher", teacher.getUsername()).groupBy(columns);
            }
        }
        return wrapper;
    }



}
